package com.example.demo.load_balance;

import org.apache.coyote.http2.Constants;

/**
 * 最小连接数算法比较灵活和智能，由于后端服务器的配置不尽相同，对于请求的处理有快有慢，它是根据后端服务器当前的连接情况，动态地选取其中当前
 *
 * 积压连接数最少的一台服务器来处理当前的请求，尽可能地提高后端服务的利用效率，将负责合理地分流到每一台服务器。
 * 下面是dubbo的实现 【最小活跃数负载均衡】
 */
//public class LeastActiveLoadBalance extends AbstractLoadBalance {
//
//    public static final String NAME = "leastactive";
//
//    private final Random random = new Random();
//
//    @Override
//    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
//        int length = invokers.size();
//        // 最小的活跃数
//        int leastActive = -1;
//        // 具有相同“最小活跃数”的服务者提供者（以下用 Invoker 代称）数量
//        int leastCount = 0;
//        // leastIndexs 用于记录具有相同“最小活跃数”的 Invoker 在 invokers 列表中的下标信息
//        int[] leastIndexs = new int[length];
//        int totalWeight = 0;
//        // 第一个最小活跃数的 Invoker 权重值，用于与其他具有相同最小活跃数的 Invoker 的权重进行对比，
//        // 以检测是否“所有具有相同最小活跃数的 Invoker 的权重”均相等
//        int firstWeight = 0;
//        boolean sameWeight = true;
//
//        // 遍历 invokers 列表
//        for (int i = 0; i < length; i++) {
//            Invoker<T> invoker = invokers.get(i);
//            // 获取 Invoker 对应的活跃数
//            int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
//            // 获取权重 - ⭐️
//            int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT);
//            // 发现更小的活跃数，重新开始
//            if (leastActive == -1 || active < leastActive) {
//                // 使用当前活跃数 active 更新最小活跃数 leastActive
//                leastActive = active;
//                // 更新 leastCount 为 1
//                leastCount = 1;
//                // 记录当前下标值到 leastIndexs 中
//                leastIndexs[0] = i;
//                totalWeight = weight;
//                firstWeight = weight;
//                sameWeight = true;
//
//                // 当前 Invoker 的活跃数 active 与最小活跃数 leastActive 相同
//            } else if (active == leastActive) {
//                // 在 leastIndexs 中记录下当前 Invoker 在 invokers 集合中的下标
//                leastIndexs[leastCount++] = i;
//                // 累加权重
//                totalWeight += weight;
//                // 检测当前 Invoker 的权重与 firstWeight 是否相等，
//                // 不相等则将 sameWeight 置为 false
//                if (sameWeight && i > 0
//                        && weight != firstWeight) {
//                    sameWeight = false;
//                }
//            }
//        }
//
//        // 当只有一个 Invoker 具有最小活跃数，此时直接返回该 Invoker 即可
//        if (leastCount == 1) {
//            return invokers.get(leastIndexs[0]);
//        }
//
//        // 有多个 Invoker 具有相同的最小活跃数，但它们之间的权重不同
//        if (!sameWeight && totalWeight > 0) {
//            // 随机生成一个 [0, totalWeight) 之间的数字
//            int offsetWeight = random.nextInt(totalWeight);
//            // 循环让随机数减去具有最小活跃数的 Invoker 的权重值，
//            // 当 offset 小于等于0时，返回相应的 Invoker
//            for (int i = 0; i < leastCount; i++) {
//                int leastIndex = leastIndexs[i];
//                // 获取权重值，并让随机数减去权重值 - ⭐️
//                offsetWeight -= getWeight(invokers.get(leastIndex), invocation);
//                if (offsetWeight <= 0)
//                    return invokers.get(leastIndex);
//            }
//        }
//        // 如果权重相同或权重为0时，随机返回一个 Invoker
//        return invokers.get(leastIndexs[random.nextInt(leastCount)]);
//    }
//}